package com.hengtiansoft.lfy.utils;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * 录音类
 *
 * Created by suyiyang on 2016/12/16.
 */

public class AudioRecordUtils {

    private int audioSource = MediaRecorder.AudioSource.MIC;
    private static int sampleRateInHz = 16000;
    private static int channelConfig = AudioFormat.CHANNEL_IN_MONO;
    private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    private int recBufSizeInBytes = 0;
    private static int waveFrameMs = 10;
    private static int waveFrameSize = sampleRateInHz * 2 * waveFrameMs / 1000;

    private static boolean isRecording = false;

    private AudioRecord audioRecord;

    private Thread audioRecordThread;

    private static final int RECORDING = 1;

    private MFRecognize mfRecognize;
    //是否开启男女声识别
    private boolean isMFRec = false;

    /**
     * 回调接口
     */
    private AudioRecordCallBack callBack;

    public AudioRecordUtils(){
        recBufSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
                channelConfig, audioFormat);
    }
    /**
     * 开始录音
     */
    public void startRecord(AudioRecordCallBack callBack){
        if(isRecording)return;
        this.callBack = callBack;

        audioRecord = new AudioRecord(audioSource, sampleRateInHz,
                channelConfig, audioFormat, Math.max(recBufSizeInBytes,
                waveFrameSize));
        audioRecord.startRecording();
        isRecording = true;

        audioRecordThread = new Thread(new AudioRecordThread());
        audioRecordThread.start();
    }

    /**
     * 停止录音
     */
    public void stopRecord(){
        if(!isRecording)return;
        isRecording = false;
        if (audioRecordThread != null) {
            try {
                audioRecordThread.join();
                audioRecordThread = null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            audioRecord.stop();
            audioRecord.release();
            audioRecord = null;
        }
        if(isMFRec && mfRecognize != null){
            int hz = mfRecognize.getFinallyHz();
            if(callBack != null){
                if(hz <= 0 || hz > MFRecognize.MAX_HZ)
                    callBack.speakGender("-1");
                else if(hz > MFRecognize.CUTTING_LINE_HZ)
                    callBack.speakGender("f");
                else
                    callBack.speakGender("m");
            }
            Log.d("tag","hz = "+hz);
        }
        callBack = null;
    }

    /**
     * 录音线程
     */
    private class AudioRecordThread implements Runnable {
        @Override
        public void run() {
            while (isRecording == true) {
                byte[] waveData = new byte[recBufSizeInBytes];
                int readSize = audioRecord.read(waveData, 0, recBufSizeInBytes);
                if (AudioRecord.ERROR_INVALID_OPERATION != readSize) {
                    if(isMFRec && mfRecognize != null){
                        mfRecognize.inputWave(waveData,0,readSize);
                    }

                    Message msg = mHandler.obtainMessage(RECORDING);
                    msg.obj = waveData;
                    msg.arg1 = 0;
                    msg.arg2 = readSize;
                    mHandler.sendMessage(msg);

                }
            }
        }
    }

    /**
     * 是否开启男女声识别
     * @param MFRec
     */
    public void setMFRec(boolean MFRec) {
        isMFRec = MFRec;
        if(MFRec && mfRecognize == null){
            mfRecognize = new MFRecognize();
        }
    }

    private Handler  mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(callBack != null){
                callBack.inputWaveData((byte[])msg.obj,msg.arg1,msg.arg2);
            }else{
                stopRecord();
            }
        }
    };

    /**
     * 录音数据回调
     */
    public interface AudioRecordCallBack{
        /**
         * 语音数据回调
         * @param data
         * @param start
         * @param count
         */
        public void inputWaveData(byte[] data,int start,int count);

        /**
         * 错误回调
         * @param err
         */
        public void error(String err);

        /**
         * 获取说话人性别
         * @param gender m男 f女 -1识别出错
         */
        public void speakGender(String gender);
    }
}
